package com.twp.auth.rest.api;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.twp.auth.annotation.MethodInfo;
import com.twp.auth.client.LoginServiceClient;
import com.twp.auth.component.Md5Component;
import com.twp.auth.config.auth.AuthConfig;
import com.twp.auth.constants.ResultCodeConstants;
import com.twp.auth.domain.authority.Menu;
import com.twp.auth.domain.authority.user.ManageUser;
import com.twp.auth.domain.authority.user.UserDetail;
import com.twp.auth.myexecption.MyBadCredentialsException;
import com.twp.auth.repository.auth.MenuRepository;
import com.twp.auth.service.user.ManageUserService;
import com.twp.auth.tuple.ExtendLoginRespBody;
import com.twp.common.tuple.auth.*;
import com.twp.common.tuple.ResultDTO;
import com.twp.common.utils.AssertUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * Created by tanweiping on 17/8/1.
 */
@Slf4j
@Api(value = "CourseController", description = "电子学习护照相关接口")
@RestController
@RequestMapping("/api/oauth/user")
public class UserLoginController  {

    @Autowired
    MenuRepository menuRepository;

    @Autowired
    AuthConfig authConfig;

    @Autowired
    Md5Component md5Component;

    @Autowired
    LoginServiceClient loginServiceClient;

    @Autowired
    ManageUserService manageUserService;

    //登录获取token
    @ApiOperation(value = "/login", notes = "登录获取token")
    @PostMapping("/login")
    public ResultDTO login(
            @RequestBody ExtendAuthBody extendAuthBody) throws Exception {

        ManageUser manageUser = manageUserService.findAllByUserName(extendAuthBody.getUsername());

        try{
            AssertUtil.isNull(manageUser,"用户不存在");
        }catch (Exception e){
            return ResultDTO.builder().isSuccess(false).code(ResultCodeConstants.NoneUser).message("用户不存在").build();
        }

        extendAuthBody.setDefaultAuthBody(DefaultAuthBody.builder().build());

        val ss = loginServiceClient.beanToMap(extendAuthBody);

        ResponseEntity<OAuth2AccessToken> tokenbody = loginServiceClient.login(
                    extendAuthBody.getContentTypePatch(),
                    extendAuthBody.getAuthorization(),
                    loginServiceClient.beanToMap(extendAuthBody)
            );

        List<Menu> menuList = menuRepository.findAllByUid(manageUser.getId());

        ExtendLoginRespBody extendLoginRespBody = ExtendLoginRespBody.builder()
                    .access_token(tokenbody.getBody().getValue())
                    .expires_in(tokenbody.getBody().getExpiresIn())
                    .refresh_token(tokenbody.getBody().getRefreshToken().getValue())
                    .scope(tokenbody.getBody().getScope().toString())
                    .token_type(tokenbody.getBody().getTokenType())
                    .name(manageUser.getName())
                    .validTime(validTime(extendAuthBody.getClientName()))
                    .roleList(manageUser.getRoleList())
                    .menuList(menuList)
                    .build();

        return ResultDTO.builder()
                .message("登录成功")
                .data(extendLoginRespBody)
                .build();
    }

    //刷新token
    @PostMapping("/refresh")
    public ResultDTO refresh(
            @RequestBody RefreshBody refreshBody
            ){
        ResponseEntity<OAuth2AccessToken> tokenbody = loginServiceClient.refresh(
                    refreshBody.getContentTypePatch(),
                    refreshBody.getAuthorization(),
                    loginServiceClient.beanToMap(refreshBody)
            );

        ExtendLoginRespBody extendLoginRespBody = ExtendLoginRespBody.builder()
                    .access_token(tokenbody.getBody().getValue())
                    .expires_in(tokenbody.getBody().getExpiresIn())
                    .refresh_token(tokenbody.getBody().getRefreshToken().getValue())
                    .scope(tokenbody.getBody().getScope().toString())
                    .token_type(tokenbody.getBody().getTokenType())
                    .validTime(validTime(refreshBody.getClientName()))
                    .build();
        return ResultDTO.builder()
                .message("刷新token成功")
                .data(extendLoginRespBody)
                .build();

    }


    private int validTime(String clientName){
        val client = authConfig
                .getClients()
                .parallelStream()
                .filter(client_ -> client_.getClientName().equals(clientName))
                .findFirst();
        int validTime=0;
        if (client.isPresent()){
            validTime = client.get().getAccessTokenValiditySeconds();
        }
        return validTime;
    }

    //@MethodInfo(code = "user_registry",description = "用户注册")
    @PostMapping("/registry")
    ResultDTO registry(@RequestBody ManageUser manageUser) throws Exception{
        ManageUser manageUserOld = manageUserService.findAllByUserName(manageUser.getUserName());
        try{
            AssertUtil.isNotNull(manageUserOld,"用户号重复");
        }catch (Exception e){
            return ResultDTO.builder().isSuccess(false).code(ResultCodeConstants.existUser).message(e.getMessage()).build();
        }
        Date d = new Date();
        manageUser.setPassword(md5Component.encode(manageUser.getPassword()));
        manageUser.setStatus(1);
        manageUser.setUpdateTime(d);
        manageUser.setCreateTime(d);
        if (manageUser.getDetail()!=null){
            UserDetail detail =  manageUser.getDetail();
            detail.setCreateTime(d);
            detail.setUpdateTime(d);
        }
        manageUserService.saveOrUpdate(manageUser);
        return ResultDTO.builder().message("用户注册成功").build();
    }


    //@MethodInfo(code = "user_password_change",description = "修改密码接口")
    @PostMapping("/password/change")
    public ResultDTO passwordChange(@RequestBody PasswordChange passwordChange){
        String message = "修改密码成功";
        boolean flag = true;
        try {
            ManageUser manageUser = manageUserService.findAllByUserName(passwordChange.getUserName());
            try{
                AssertUtil.isNull(manageUser,"账号异常");
            }catch (Exception e){
                return ResultDTO.builder().isSuccess(false).code(ResultCodeConstants.NoneUser).message(e.getMessage()).build();
            }

            if (!md5Component.matches(passwordChange.getOldPassword(),manageUser.getPassword())){
                //throw new Exception("旧密码不正确");
                return ResultDTO.builder().isSuccess(false).code(ResultCodeConstants.errorOldPwd).message("旧密码不正确").build();
            }
            manageUser.setPassword(md5Component.encode(passwordChange.getNewPassword()));
            manageUserService.saveOrUpdate(manageUser);

        }catch (Exception e){
            log.error("修改密码接口成功出现异常:"+e.toString());
            return ResultDTO.builder()
                    .isSuccess(false)
                    .message("修改密码接口成功出现异常:"+e.toString())
                    .build();
        }
        return ResultDTO.builder()
                .isSuccess(flag)
                .message(message)
                .build();
    }
    @GetMapping("/currentUser")
    @MethodInfo(code = "currentUser_info",description = "用户信息查询接口")
    public ResultDTO getUserInfoByAccount(Principal principal) throws Exception {
        ResultDTO resultDTO = ResultDTO
                .builder()
                .message("用户信息查询成功")
                .build();
        try {
            ManageUser manageUser =  manageUserService.findAllByUserName(principal.getName());
            resultDTO.setData(
                    new HashMap<String,Object>(){
                        {
                            put("id",manageUser.getId());
                            put("account",manageUser.getUserName());
                            put("name",manageUser.getName());
                            put("sex",manageUser.getSex());
                        }
                    }
            );
        }catch (Exception e){
            throw new Exception("用户信息查询失败");
        }
        return resultDTO;
    }
}
